package it.univpm.diiga.memorysim.data;


import it.univpm.diiga.memorysim.kernel.shared.Kernel;
import it.univpm.diiga.memorysim.kernel.shared.Parameters;
import it.univpm.diiga.memorysim.kernel.shared.ProcessRequest;
import it.univpm.diiga.memorysim.kernel.shared.Process;
import it.univpm.diiga.memorysim.kernel.shared.FileRequest;
import it.univpm.diiga.memorysim.kernel.shared.tree.MovingBox;
import it.univpm.diiga.memorysim.views.SelectSimulation;

import java.io.Serializable;
import java.util.ArrayList;

import org.eclipse.jface.dialogs.MessageDialog;

public class DataPlugin implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public static int SimType=0;
	public static Kernel kernel=new Kernel();
	public static String SimSelected = null;//Possibili valori -> {"Paginazione","Segmentazione","Segmentazione con Paginazione"};
	public static String SimSelected1 = null; //Possibili valori -> {"Random"};
	public static String AlgSelected = null;	//Possibili valori -> {"Dummy"};
	public static String HddValor="Maxtor Ultra Hard Drive Kit 160 GB ATA-133,160,4,133,9,9\nMaxtor Ultra Hard Drive Kit 320 GB ATA-133,320,4,133,9,9";
	//NOME,DimensioneDisco,DimensioneBlocco,VelocitàdiTrasferimento,Seek,Revolution
	
	//Memoria riservata al sistema operativo [Mb]
	private static int dimSOMemory=200; 
	
	//liste processi
	public static ArrayList<Process> listProcess=new ArrayList<Process>();
	//Numero di segmenti in un processo
	public static ArrayList<Integer> listSegmentP=new ArrayList<Integer>();

	
	public static ArrayList<ProcessRequest> listProcessRequest=null;
	public static ArrayList<FileRequest> listFileRequest=new ArrayList<FileRequest>();
	public static boolean isNewlistProcess=false;
	
	//Dimensione memoria centrale
	public static int memorycentraldata=0;
	public static int swapdata=0;
	//Dimensione blocco (=dimensione pagina)
	public static int blockdata=0;
	
	// roba di harddisk
	public static int hdddimensionblockdata=0;
	public static int trasferratedata=0;
	public static int seekdata=0;
	public static int hdddimensiondata=0;
	public static int revolutiontimedata=0;
	public static int hddused=0; // Kbyte
	public static int ramUsed=0; // Kbyte
	private static int idFileRequest=0;
	
	
	//root of file system
	public static MovingBox root=null;
	
	//Situazione Iniziale delle memoria centrale e swap
	public static ArrayList<String> CentralMemoryP=null;
	public static ArrayList<String> SwapMemoryP=null;
	
	public static String setDefaultHDDvalue(){
		return HddValor;
	}
	
	public void setSimType(){
		
	}

	public static ArrayList<Process> getlistProcess() {
		return listProcess;
	}
	
	public static void newProcessRequest(){
		listProcessRequest=new ArrayList<ProcessRequest>();
	}

	public static void addProcessRequest(int pid, int page, String type){
		System.out.println("process: "+pid);
		System.out.println("dim processes:"+listProcess.get(0).getDimProcess());
		//public ProcessRequest(int PID,int pagina,int offset, int dimProcess, int durata, boolean lastRequest){
		
		int dimProc = listProcess.get(pid-1).getDimProcess();
		int offset = 0, durata = 0;
		boolean lastRequest = false;
		ProcessRequest request= new ProcessRequest(pid,page-1, offset,dimProc, durata, lastRequest);
		
		listProcessRequest.add(request);
	}
	public static void addProcessRequest(int pid, int seg,String type, int dim) {
		//ProcessRequest(int PID,int segmento,int offset, int dimSegmento, int dimProcess, int durata)
		int dimProc = listProcess.get(pid-1).getDimProcess();
		System.out.println("dim processes:"+listProcess.get(pid-1).getDimProcess()+" seg "+ seg+" pid " + pid+ " dim seg "+ dim);
		ProcessRequest request= new ProcessRequest(pid,seg-1,dim-1,dim,dimProc,11);
		listProcessRequest.add(request);
		
		/*ProcessRequest p1 = new ProcessRequest(1,0,50,100,100,3);  
		ProcessRequest p2 = new ProcessRequest(2,0,30,50,50,4);
		ProcessRequest p3 = new ProcessRequest(3,0,60,100,100,7);
		ProcessRequest p4 = new ProcessRequest(4,0,30,50,50,7);
		ProcessRequest p5 = new ProcessRequest(5,0,30,50,50,3);
		listProcessRequest.add(p1);
		listProcessRequest.add(p2);
		listProcessRequest.add(p3);
		listProcessRequest.add(p4);
		listProcessRequest.add(p5);
		*/
	}
	
	public static void newProcessList(){
		listProcess=new ArrayList<Process>();
	}

	public static void addProcess(int i, int n) {
		Process proc = new Process(i,n);
		int dim=0;
		//if(SimSelected=="Paginazione") 
			dim=n/DataPlugin.blockdata;
		//if(SimSelected=="Segmentazione") dim=n/DataPlugin.SegmentDimension;
		proc.setTableDim(dim);
		listProcess.add(proc);
	}

	public static int getDimProcess(int PID) {
		Process proc = listProcess.get(PID);
		return proc.getDimProcess();
	}
	
	public static void newFileListRequest(){
		listFileRequest=new ArrayList<FileRequest>();
	}
	
	public static ArrayList<FileRequest> getFileListRequest(){
		return listFileRequest;
	}
	public static void addFileRequest(String Nome, int dim, String Path,String Op) {
		if(dim>0)	//listFileRequest.add(new FileRequest(Nome,"Dir", dim, Path,Op));
		{
			if (Op.equals("Lettura"))
				listFileRequest.add(new FileRequest(idFileRequest,Nome,"File", dim, Path,0));
			if (Op.equals("Scrittura"))
				listFileRequest.add(new FileRequest(idFileRequest,Nome,"File", dim, Path,1));
			if (Op.equals("Creazione file"))
				listFileRequest.add(new FileRequest(idFileRequest,Nome,"File", dim, Path,2));
			if (Op.equals("Cancellazione"))
				listFileRequest.add(new FileRequest(idFileRequest,Nome,"File", dim, Path,3));
		}
		
		System.out.println("IDRequest: "+idFileRequest+" Nome File "+Nome+" Dimensione "+dim+" Operazione "+Op);
		
		//idFileRequest++;
	}
	
	
	public static void initSimulation(){
		try{
				int Full_used=((hddused/1024)+swapdata)/1024; // in Gb
				if(hdddimensiondata<Full_used) MessageDialog.openWarning(null, "Attenzione", "La simulazione rischia di usare più memoria di quella disponibile nell'harddisk");
				if((dimSOMemory+memorycentraldata+swapdata)<(ramUsed/1024)) MessageDialog.openWarning(null, "Attenzione", "La simulazione rischia di usare più memoria di quella disponibile per i processi");
				
				
				kernel.setHardware(memorycentraldata,swapdata,blockdata,hdddimensiondata,trasferratedata,
						seekdata,revolutiontimedata,hdddimensionblockdata);
				
				kernel.setDimSOMemory(dimSOMemory);
				
				if(SimType==1) kernel.activeSimType1();
				if(SimType==2) kernel.activeSimType2();
				if(SimType==3){
					kernel.activeSimType1();
					kernel.activeSimType2();
				}
				
				if(kernel.isactiveSimType1()){
					kernel.selectedAlgorithmCentMem(AlgSelected);
					kernel.setListProcess(listProcess,CentralMemoryP,SwapMemoryP);
					kernel.setListProcessRequest(listProcessRequest);
				}
				
				if(kernel.isactiveSimType2()){
					kernel.selectedAlgorithmSecMem(SimSelected1);
					kernel.setFileSystem(root);
					kernel.setListFileRequest(listFileRequest);
				}
				
				Situation.resultSimulation();
				
		}catch(Exception e){
			MessageDialog.openInformation(null,"Errore","Errore di inizializzazione della simulazione:\n controllare i paramentri inseriti");
		}
	}


	
	public static int findProcessRequestDim(int proc, int seg){
		int dim=1;
		if(listProcessRequest!=null){
		for(int i=0; i<listProcessRequest.size();i++){
		ProcessRequest pr = listProcessRequest.get(i);
		if(pr.getPID()==proc && pr.getSegmento()==seg) dim=pr.getDimBlock();
		}}
		return dim;
	}
	
	public static void reset(){
		SimType=0;
		SimSelected = null;
		SimSelected1 = null;
		AlgSelected = null;
		dimSOMemory=200; 
		listProcess=new ArrayList<Process>();
		listSegmentP=new ArrayList<Integer>();
		listProcessRequest=new ArrayList<ProcessRequest>();
		listFileRequest=new ArrayList<FileRequest>();
		isNewlistProcess=false;
		memorycentraldata=0;
		swapdata=0;
		blockdata=0;
		hdddimensionblockdata=0;
		trasferratedata=0;
		seekdata=0;
		hdddimensiondata=0;
		revolutiontimedata=0;
		hddused=0; 
		ramUsed=0; 
		root=null;
		CentralMemoryP=null;
		SwapMemoryP=null;
		SelectSimulation.resetSelection();
	}

	public static void saveInitialMemory(String[] dataMem) {
		CentralMemoryP=new ArrayList<String>();
		for(String mem: dataMem) CentralMemoryP.add(mem);
	}

	public static void saveInitialSwap(String[] dataSwap) {
		SwapMemoryP=new ArrayList<String>();
		for(String mem: dataSwap) SwapMemoryP.add(mem);
	}
	
	public static boolean ControlMem(){
		if(listProcessRequest!=null && listProcess!=null){
		if(listProcessRequest.size()>0 && listProcess.size()>0) return true;}
		return false;
	}
	
	public static boolean ControlDisk(){
		if(listFileRequest!=null) if(listFileRequest.size()>0) return true;
		return false;
	}
}